<?php
///////////////////////////////////////////////////////////////////////////////////////////////////////
//  这个文件是 JCAT PHP框架的一部，该项目和此文件 均遵循 GNU 自由软件协议
// 
//  Copyleft 2008 JeCat.cn(http://team.JeCat.cn)
//
//
//  JCAT PHP框架 的正式全名是：Jellicle Cat PHP Framework。
//  “Jellicle Cat”出自 Andrew Lloyd Webber的音乐剧《猫》（《Prologue:Jellicle Songs for Jellicle Cats》）。
//  JCAT 是一个开源项目，它像音乐剧中的猫一样自由，你可以毫无顾忌地使用JCAT PHP框架。JCAT 由中国团队开发维护。
//  正在使用的这个版本是：0.6.0 / SVN信息: $Id: class.Locale.php 2153 2009-12-16 14:45:04Z alee $
//
//
//
//  相关的链接：
//    [主页] http://jcat.JeCat.cn
//    [下载(HTTP)] http://code.google.com/p/jcat-php/downloads/list
//    [下载(svn)] svn checkout http://jcat-php.googlecode.com/svn/branches/0.4.0/Framework/ JCAT0.4
//    [在线文档] http://jcat.JeCat.cn/document
//    [社区] http://jj.jecat.cn/forum-7-1.html
//  不很相关：
//    [MP3] http://www.google.com/search?q=jellicle+songs+for+jellicle+cats+Andrew+Lloyd+Webber
//    [VCD/DVD] http://www.google.com/search?q=CAT+Andrew+Lloyd+Webber+video
//
///////////////////////////////////////////////////////////////////////////////////////////////////////
/*-- Project Introduce --*/

namespace JCAT\Core\Locale ;

include_once __DIR__.'/class.Language.php' ;
include_once __DIR__.'/class.LanguagePackage.php' ;


use JCAT\Core ;
use JCAT\Core\OOP ;
use JCAT\Core\Assert ;

class Locale
{
	/**
	 * Description
	 *
	 * @access	public
	 * @return	Locale
	 * @static
	 */
	static public function GetGlobalInstance()
	{
		if( !self::$aGlobalInstance )
		{
			self::$aGlobalInstance = new self() ;
		}
		
		return self::$aGlobalInstance ;
	}

	/**
	 * 根据语言名称，创建 或 取得已创建 的 语言实例（享元模式）
	 * 
	 * @access	public
	 * @param	$sLanguageName	string	语言名称
	 * @return	Language
	 */
	public function GetLanguage( $sLanguageNameIpt ) 
	{
		$sLanguageName = strtolower($sLanguageNameIpt) ;
		
		if( isset($this->arrLanguageInses[$sLanguageName]) )
		{
			return $this->arrLanguageInses[$sLanguageName] ;
		}

		$aLanguage = new Language($sLanguageName) ;
		$this->arrLanguageInses[$sLanguageName] = $aLanguage ;

		// 若无默认语言实例,自动 设置为 默认语言实例
		if( !$this->aDefaultLanguage )
		{
			$this->aDefaultLanguage = $aLanguage ;
		}
		
		return $aLanguage ;
	}

	/**
	 * 设置默认语言包
	 * 
	 * @access	public
	 * @param	$Language	Language,string	语言实例，或语言名称
	 * @return	old_value
	 */
	public function SetDefaultLanguage( $Language ) 
	{
		$old_value = $this->GetDefaultLanguage() ;

		if( is_string($Language) )
		{
			$this->aDefaultLanguage = $this->GetLanguage($Language) ;
		}
		elseif( OOP\IsKindOf('JCAT\\Core\\Locale\\Language') )
		{
			$this->aDefaultLanguage = $Language ;
		}
		else
		{
			throw new Core\Exception('paramter type is wrong') ;
		}

		return $old_value ;
	}

	/**
	 * 返回默认语言包
	 * 
	 * @access	public
	 * @return	Language
	 */
	public function GetDefaultLanguage() 
	{
		return $this->aDefaultLanguage ;
	}
	
	/**
	 * Description
	 *
	 * @access	public
	 * @param	$sPkgName
	 * @return	void
	 */
	public function SetDefaultPackage($sPkgName)
	{
		$this->sDefaultPkgName = $sPkgName ;
	}
	
	/**
	 * Description
	 *
	 * @access	public
	 * @return	string
	 */
	public function GetDefaultPackage()
	{
		return $this->sDefaultPkgName ;
	}

	/**
	 * Description
	 *
	 * @access	public
	 * @param	$Parameter
	 * @return	void
	 */
	public function RegisterLangPackage($sPackageName,$sFolderPath)
	{
		Assert\IS_DIR($sFolderPath) ;
		$this->arrPackages[$sPackageName] = $sFolderPath ;
	}
	
	/**
	 * Description
	 *
	 * @access	public
	 * @param	$sPackageName
	 * @return	void
	 */
	public function QueryNamespace($sNSPkgName)
	{
		$sFoundPkgName = '' ;
		
		foreach($this->arrPackages as $sRgrPkgName=>$sFolderPath)
		{
			if( strstr($sNSPkgName,$sRgrPkgName) )
			{
				if( $sNSPkgName==$sRgrPkgName)
				{
					return $sRgrPkgName ;
				}
				
				if( strlen($sRgrPkgName)>strlen($sFoundPkgName) )
				{
					$sFoundPkgName = $sRgrPkgName ;
				}
			}
		}
		
		return $sFoundPkgName ;
	}
	
	/**
	 * Description
	 *
	 * @access	public
	 * @param	$sPackageName
	 * @return	string
	 */
	public function GetPackageFolder($sPackageName)
	{
		return isset($this->arrPackages[$sPackageName])? $this->arrPackages[$sPackageName]: null ;
	}

	/**
	 * 从指定语言的指定语言包取得一条语句
	 * 
	 * @access	public
	 * @param	$sSentence		sting							原始语句
	 * @param	$sPackageName	string							语言包名称、语言包实例 或 null(使用默认语言包)
	 * @param	$Language		string,Language,null		语言名称、语言实例 或 null(使用默认语言)
	 * @param	Argvs... ...	mixed							代入语句的参数
	 * @return	string
	 */
	public function SentenceEx( $sSentence,  $sPackageName=null,  $Language=null /* Argvs... ...*/ ) 
	{
		// 参数类型检验 ...
		Assert\IS_STRING($sSentence,'参数 $sSentence 必须为 string 类型') ;
		Assert\IS_THESE($Language,array('null','string','JCAT\\Core\\Locale\\LanguagePackage'),'null','参数 $Language 必须为 语言名称(string 类型)，已创建的语言对象(Language 类型)，或 null（使用默认语言）') ;
		Assert\IS_STRING($sPackageName,'参数 $sPackageName 必须为 语言包名称，或 null（使用默认语言包）') ;

		// 语句 Key
		$sSentenceKey = MakeSentenceKey($sSentence) ;
		
		
		// 取得 语言享员对象
		// ---------------------------
		// 语言名称
		if( is_string($Language) )
		{
			$theLanguage = $this->GetLanguage($Language) ;
		}
		
		// 已创建的语言对象
		else if( OOP\IsKindOf($Language,'JCAT\\Core\\Locale\\Language') )
		{
			$theLanguage = $Language ;
		}
		
		// 缺省：默认语言对象
		else if( $Language===null )
		{
			$theLanguage = $this->GetDefaultLanguage() ;
			if(!$theLanguage)
			{
				throw new Core\Exception("尚未指定默认语言。",__FUNCTION__,__LINE__,'$Revision: 2153 $') ;
			}
		}
		
		if(!$sPackageName)
		{
			if( !$sPackageName=$this->GetDefaultPackage() )
			{
				throw new Core\Exception("尚未指定默认语言包。",__FUNCTION__,__LINE__,'$Revision: 2153 $') ;
			}
		}

		// 取得 语言包 对象
		// ---------------------------
		if( !$thePackage=$theLanguage->GetPackage($sPackageName) )
		{
			if( !$sNSPkgName=$this->QueryNamespace($sPackageName) )
			{
				throw new Core\Exception("尚未指定语言包：“{$sPackageName}”的存放目录。",__FUNCTION__,__LINE__,'$Revision: 2153 $') ;
			}
			
			$sLangName = $theLanguage->GetLanguageName() ;
			$sPkgFolder = $this->GetPackageFolder($sNSPkgName) ;
			$thePackage = new LanguagePackage($sLangName,$sNSPkgName,$sPkgFolder) ;
			$theLanguage->AddPackage($thePackage) ;
		}
		
		Assert\IS_NOTNULL($thePackage,'?!') ;
	
		// 语句存在
		if($thePackage->Has($sSentenceKey))
		{
			$sRealSentence = $thePackage->Get($sSentenceKey) ;
		}
		
		// 语句不存在，使用原文
		else
		{
			$sRealSentence = $sSentence ;
			$thePackage->Set($sSentenceKey, $sRealSentence) ;
		}
		
		
		// 代入参数
		if( func_num_args() > 3 )
		{
			$arrArgs = func_get_args() ;
			$arrArgs[0] = $sRealSentence ;
			unset($arrArgs[1],$arrArgs[2]) ;
			
			// 将参数中为null的参数转换成字串'Null'
			foreach ($arrArgs as $nIdx=>&$Arg)
			{
				if( $nIdx>0 and $Arg===null )
				{
					$Arg = 'Null' ;
				}
			}
			$sRealSentence = call_user_func_array('sprintf',$arrArgs) ;
		}

		return $sRealSentence ;
	}

	/**
	 * 从默认语言的默认语言包取得一条语句
	 * 
	 * @access	public
	 * @param	$sSentence		string	语句
	 * @param	Argvs... ...	mixed	参数
	 * @return	string
	 */
	function Sentence(  $sSentence  /* Argvs... ...*/ ) 
	{
		$arrArgs = func_get_args() ;
		unset($arrArgs[0]) ;
		array_unshift($arrArgs,$sSentence,null,null) ;
		
		return call_user_func_array( array(__CLASS__,'SentenceEx'), $arrArgs ) ;
	}

	/**
	 * 已创建的语言实例（享元模式）
	 * 
	 * @access	private
	 * @var		array
	 */
	private $arrLanguageInses = array() ;

	/**
	 * 默认语言实例
	 * 
	 * @access	private
	 * @var		Language
	 */
	private $aDefaultLanguage = null ;
	
	/**
	 * 默认语言实例
	 * 
	 * @access	private
	 * @var		string
	 */
	private $sDefaultPkgName = '' ;
	
	/**
	 * Description
	 * 
	 * @access	private
	 * @var		array
	 */
	private $arrPackages = array() ;
	
	/**
	 * Description
	 * 
	 * @access	private
	 * @static
	 * @var		Locale
	 */
	static private $aGlobalInstance ;
}



/**
 * 根据语句内容产生Key
 * 
 * @access	public
 * @param	$sSentence	string	语句内容
 * @return	string	
 */
function MakeSentenceKey( $sSentence ) 
{
	return md5($sSentence) ;
}


/**
 * 从指定语言的指定语言包取得一条语句
 * 
 * @access	public
 * @param	$sSentence		sting							原始语句
 * @param	$sPackageName	string							语言包名称、语言包实例 或 null(使用默认语言包)
 * @param	$Language		string,Language,null			语言名称、语言实例 或 null(使用默认语言)
 * @param	Argvs... ...	mixed							代入语句的参数
 * @return	string
 */
function sx( $sSentence,  $sPackageName=null,  $Language=null /* Argvs... ...*/ ) 
{
	$arrAgrvs = func_get_args() ;
	return call_user_func_array( 
		array(
			Locale::GetGlobalInstance()
			, 'SentenceEx'
		)
		,  $arrAgrvs
	) ;
}

/**
 * 从默认语言的默认语言包取得一条语句
 * 
 * @access	public
 * @param	$sSentence		string	语句
 * @param	Argvs... ...	mixed	参数
 * @return	string
 */
function s( $sSentence  /* Argvs... ...*/ )
{
	$arrAgrvs = func_get_args() ;
	return call_user_func_array( 
			array(
				Locale::GetGlobalInstance()
				, 'Sentence'
			)
			,  $arrAgrvs
	) ;	
}


?>